//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package events_subscribe_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/event_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/events_subscribe_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
	"google.golang.org/protobuf/proto"
)

type EventSubscribeApiImpl struct {
	events_subscribe_api.UnimplementedEventSubscribeApiServer
}

func (apiImpl *EventSubscribeApiImpl) Create(ctx context.Context, req *events_subscribe_api.CreateRequest) (*events_subscribe_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &events_subscribe_api.CreateResponse{
			Code:   events_subscribe_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &events_subscribe_api.CreateResponse{
			Code:   events_subscribe_api.CreateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &events_subscribe_api.CreateResponse{
			Code:   events_subscribe_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	if projectItem.Closed {
		return &events_subscribe_api.CreateResponse{
			Code:   events_subscribe_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &events_subscribe_api.CreateResponse{
			Code:   events_subscribe_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if req.ChatBotType == events_subscribe_api.CHAT_BOT_TYPE_CHAT_BOT_DING || req.ChatBotType == events_subscribe_api.CHAT_BOT_TYPE_CHAT_BOT_FS {
		if req.ChatBotSignCode == "" {
			return &events_subscribe_api.CreateResponse{
				Code:   events_subscribe_api.CreateResponse_CODE_NEED_SIGN_CODE,
				ErrMsg: "签名令牌不能为空",
			}, nil
		}
	}
	req.EventCfg = apiImpl.adjustEventCfg(req.EventCfg)
	evCfgData, err := proto.Marshal(req.EventCfg)
	if err != nil {
		return nil, err
	}

	subscribeId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = event_dao.SubscribeDao.Insert(sessCtx, &event_dao.SubscribeInfoDbItem{
			SubscribeId:     subscribeId,
			ProjectId:       req.ProjectId,
			ChatBotName:     req.ChatBotName,
			ChatBotType:     uint32(req.ChatBotType),
			ChatBotAddr:     req.ChatBotAddr,
			ChatBotSignCode: req.ChatBotSignCode,
			EventCfgData:    evCfgData,
			CreateTime:      nowTime,
			CreateUserId:    sessionItem.UserId,
			UpdateTime:      nowTime,
			UpdateUserId:    sessionItem.UserId,
		})
		if err != nil {
			return nil, err
		}
		return &events_subscribe_api.CreateResponse{
			Code:        events_subscribe_api.CreateResponse_CODE_OK,
			SubscribeId: subscribeId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addCreateEventSubscribeEvent(sessionItem, req, projectItem, subscribeId, nowTime)
	return ret.(*events_subscribe_api.CreateResponse), nil
}

func (apiImpl *EventSubscribeApiImpl) Update(ctx context.Context, req *events_subscribe_api.UpdateRequest) (*events_subscribe_api.UpdateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	if projectItem.Closed {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	subItem, err := event_dao.SubscribeDao.Get(ctx, req.ProjectId, req.SubscribeId)
	if err != nil {
		return &events_subscribe_api.UpdateResponse{
			Code:   events_subscribe_api.UpdateResponse_CODE_NO_SUBSCRIBE,
			ErrMsg: "事件订阅不存在",
		}, nil
	}

	req.EventCfg = apiImpl.adjustEventCfg(req.EventCfg)
	evCfgData, err := proto.Marshal(req.EventCfg)
	if err != nil {
		return nil, err
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = event_dao.SubscribeDao.Update(sessCtx, req.ProjectId, req.SubscribeId, req.ChatBotName, evCfgData, nowTime, sessionItem.UserId)
		if err != nil {
			return nil, err
		}
		return &events_subscribe_api.UpdateResponse{
			Code: events_subscribe_api.UpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addUpdateEventSubscribeEvent(sessionItem, req, projectItem, subItem, nowTime)
	return ret.(*events_subscribe_api.UpdateResponse), nil
}

func (apiImpl *EventSubscribeApiImpl) adjustEventCfg(evCfg *events_subscribe_api.EventCfg) *events_subscribe_api.EventCfg {
	//保证所有配置非空(客户端版本差异造成)
	if evCfg.CodeEvCfg == nil {
		evCfg.CodeEvCfg = &events_subscribe_api.CodeEvCfg{}
	}
	if evCfg.IdeaEvCfg == nil {
		evCfg.IdeaEvCfg = &events_subscribe_api.IdeaEvCfg{}
	}
	if evCfg.AtomgitEvCfg == nil {
		evCfg.AtomgitEvCfg = &events_subscribe_api.AtomgitEvCfg{}
	}
	if evCfg.EntryEvCfg == nil {
		evCfg.EntryEvCfg = &events_subscribe_api.EntryEvCfg{}
	}
	if evCfg.HarborEvCfg == nil {
		evCfg.HarborEvCfg = &events_subscribe_api.HarborEvCfg{}
	}
	if evCfg.TestcaseEvCfg == nil {
		evCfg.TestcaseEvCfg = &events_subscribe_api.TestcaseEvCfg{}
	}
	return evCfg
}

func (apiImpl *EventSubscribeApiImpl) List(ctx context.Context, req *events_subscribe_api.ListRequest) (*events_subscribe_api.ListResponse, error) {
	emptyList := []*events_subscribe_api.SubscribeInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &events_subscribe_api.ListResponse{
			Code:     events_subscribe_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			InfoList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &events_subscribe_api.ListResponse{
			Code:     events_subscribe_api.ListResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			InfoList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &events_subscribe_api.ListResponse{
			Code:     events_subscribe_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			InfoList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	subItemList, err := event_dao.SubscribeDao.List(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	//补充成员信息
	userIdList := []string{}
	for _, subItem := range subItemList {
		userIdList = append(userIdList, subItem.CreateUserId)
		if subItem.UpdateUserId != subItem.CreateUserId {
			userIdList = append(userIdList, subItem.UpdateUserId)
		}
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//生成结果
	infoList := []*events_subscribe_api.SubscribeInfo{}
	for _, subItem := range subItemList {
		info, err := subItem.ToSubscribeInfo()
		if err != nil {
			continue
		}
		info.EventCfg = apiImpl.adjustEventCfg(info.EventCfg)
		createMember, ok := userItemMap[subItem.CreateUserId]
		if ok {
			info.CreateDisplayName = createMember.BasicInfo.DisplayName
			info.CreateLogoUri = createMember.BasicInfo.LogoUri
		}
		updateMember, ok := userItemMap[subItem.UpdateUserId]
		if ok {
			info.UpdateDisplayName = updateMember.BasicInfo.DisplayName
			info.UpdateLogoUri = updateMember.BasicInfo.LogoUri
		}
		infoList = append(infoList, info)
	}

	return &events_subscribe_api.ListResponse{
		Code:     events_subscribe_api.ListResponse_CODE_OK,
		InfoList: infoList,
	}, nil
}

func (apiImpl *EventSubscribeApiImpl) Remove(ctx context.Context, req *events_subscribe_api.RemoveRequest) (*events_subscribe_api.RemoveResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	if projectItem.Closed {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	subItem, err := event_dao.SubscribeDao.Get(ctx, req.ProjectId, req.SubscribeId)
	if err != nil {
		return &events_subscribe_api.RemoveResponse{
			Code:   events_subscribe_api.RemoveResponse_CODE_NO_SUBSCRIBE,
			ErrMsg: "事件订阅不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = event_dao.SubscribeDao.Remove(sessCtx, req.ProjectId, req.SubscribeId)
		if err != nil {
			return nil, err
		}
		return &events_subscribe_api.RemoveResponse{
			Code: events_subscribe_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addRemoveEventSubscribeEvent(sessionItem, projectItem, subItem)
	return ret.(*events_subscribe_api.RemoveResponse), nil
}
